Game functions and variables topic
Share state with the story: its variables, functions the game provides, and ink functions the game calls.
Variables
Global variables (VAR in ink) are read and written through
variablesState. Set them before the first continueStory so the ink
sees them from its first line.
story.variablesState['strength'] = 3; // int
story.variablesState['name'] = 'Ada'; // String
final gold = story.variablesState['gold']; // int, double, String, bool or InkList
for (final name in story.variablesState) { /* every global */ }
Only variables the ink declares can be set; anything else throws a
StoryException.
Watching variables
story.observeVariable('gold', (name, value) => hud.gold = value as int);
At the end of each continueStory, the observer runs once for each watched
variable that changed, with its latest value. Changes the engine makes
while looking ahead (see below) and then rewinds don't count. Remove an
observer with removeVariableObserver.
External functions
Declare a function in ink with EXTERNAL roll(sides), then bind it before
the first continueStory:
story.bindExternalFunction1<int>('roll', (sides) => rng.nextInt(sides) + 1);
story.bindExternalFunction2<String, int>('give', (item, count) {
inventory.add(item, count); // returning nothing returns nothing to ink
});
bindExternalFunction0 to bindExternalFunction4 convert each argument to
the type you declare, as the C# runtime does: a float passed to an int
parameter rounds (halves to even), an int becomes a double or a bool, and
any value can be taken as a String. bindExternalFunctionGeneral passes
the raw values instead.
Lookahead. To decide whether the next line is glued to this one, the
engine sometimes runs a little past the end of a line and then rewinds. A
function bound with lookaheadSafe: false (the default) is never called
during that lookahead: the engine stops there instead. Pass true only for
functions with no side effects, such as a pure calculation.
If a function isn't bound, the first continueStory throws a
StoryException naming every missing function, whether or not onError is
set. With allowExternalFunctionFallbacks = true,
an ink function of the same name is called instead, so a story can run in
Inky without the game:
EXTERNAL roll(sides)
=== function roll(sides) ===
~ return RANDOM(1, sides)
Calling ink functions
final price = story.evaluateFunction('price_of', ['sword']);
final r = story.evaluateFunctionWithOutput('describe', ['sword']);
print(r.textOutput); // any text the function printed
print(r.result); // its return value
Arguments may be int, double, String, bool or InkList. A function
returning a divert target returns its path as a string.
Lists
An ink LIST variable comes back as an InkList, a set of InkListItems
with their values:
final inventory = story.variablesState['inventory'] as InkList;
if (inventory.containsItemNamed('lantern')) { ... }
print(inventory); // "lantern, rope", in value order
Classes
- InkList Game functions and variables
-
The value of an ink list variable: a set of items, each with its int
value. Derives from
Dictionary<InkListItem, int>in the reference; iteration follows .NET's dictionary order (seeDotNetDictionary). - InkListItem Game functions and variables
- The name of a list item, qualified by the list it comes from. A struct in the reference: an immutable value here.
- Story Getting started Game functions and variables Saving and loading Flows Matching Unity and Inky
- A Story is the core class that represents a complete Ink narrative, and manages the evaluation and state of it.
- VariablesState Game functions and variables
- Encompasses all the global variables in an ink Story, and allows binding of a VariableChanged event so that that game code can be notified whenever the global variables change.